package com.ljq.rpc.client.utils;

import com.ljq.rpc.annotations.Deposit;
import com.ljq.rpc.client.proxy.ProxyFactory;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Set;

public class AutoMapperScanClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
    public AutoMapperScanClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
        super(registry, useDefaultFilters);
    }

    /**
     * description: 负责对接口代理进行定义
     * version: 1.0
     * date: 2021/3/13 11:04
     * author: Silwings
     *
     * @return void
     */
    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        // 添加过滤器,只扫描添加了NeedProxy注解的类
        addIncludeFilter(new AnnotationTypeFilter(Deposit.class));
        Set<BeanDefinitionHolder> beanDefinitionHolderSet = super.doScan(basePackages);
        // 对扫描到的数据进行代理处理
        processBeanDefinitions(beanDefinitionHolderSet);
        return beanDefinitionHolderSet;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitionHolderSet) {
        beanDefinitionHolderSet.forEach(e -> {
            // 设置工厂等操作需要基于GenericBeanDefinition，BeanDefinitionHolder是其子类
            GenericBeanDefinition definition = (GenericBeanDefinition) e.getBeanDefinition();
            // 获取接口的全路径名称
            String beanClassName = definition.getBeanClassName();
            // 设置构造函数参数
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
            // 设置工厂
            definition.setBeanClass(ProxyFactory.class);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        });
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

}
